package com.ruoyi.hikvision.hk;

import com.ruoyi.hikvision.NetSDK.HCNetSDK;
import com.ruoyi.hikvision.hk.commom.osSelect;
import com.sun.jna.Native;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HikvisionService {

    private static HikvisionService mInstance;
    private HCNetSDK hCNetSDK = null;
    private final Map<String, HikvisionClient> clientMap = new HashMap<>();

    public Map<String, HikvisionClient> getClientMap() {
        return clientMap;
    }

    public static HikvisionService getInstance() {
        if (mInstance == null) {
            synchronized (HikvisionService.class) {
                mInstance = new HikvisionService();
            }
        }
        return mInstance;
    }

    // 初始化SDK
    public void initSDK() {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                String strDllPath = "";
                try {
                    if (osSelect.isWindows()) {
                        // win系统加载库路径
                        strDllPath = System.getProperty("user.dir") + "\\ruoyi-hikvision\\libs\\win64\\HCNetSDK.dll";

                        System.out.println("win系统加载库路径:"+strDllPath);
                    } else if (osSelect.isLinux()) {
                        // linux系统加载库路径
                        strDllPath = System.getProperty("user.dir") + "/ruoyi-hikvision/libs/linux/libhcnetsdk.so";
                    }
                    hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
                } catch (Exception ex) {
                    hCNetSDK = null;
                    System.err.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
                }
            }
        }
        if (hCNetSDK == null) return;
        // linux系统加载组件库
        if (osSelect.isLinux()) {
            try {
                // 加载组件库
                String strPath1 = System.getProperty("user.dir") + "/ruoyi-hikvision/libs/linux/libcrypto.so.1.1";
                HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
                System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
                ptrByteArray1.write();
                hCNetSDK.NET_DVR_SetSDKInitCfg(HCNetSDK.NET_SDK_INIT_CFG_LIBEAY_PATH, ptrByteArray1.getPointer());
                // 加载组件库
                String strPath2 = System.getProperty("user.dir") + "/ruoyi-hikvision/libs/linux/libssl.so.1.1";
                HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
                System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
                ptrByteArray2.write();
                hCNetSDK.NET_DVR_SetSDKInitCfg(HCNetSDK.NET_SDK_INIT_CFG_SSLEAY_PATH, ptrByteArray2.getPointer());
                // 加载组件库
                String strPathCom = System.getProperty("user.dir") + "/ruoyi-hikvision/libs/linux/";
                HCNetSDK.NET_DVR_LOCAL_SDK_PATH strComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
                System.arraycopy(strPathCom.getBytes(), 0, strComPath.sPath, 0, strPathCom.length());
                strComPath.write();
                hCNetSDK.NET_DVR_SetSDKInitCfg(HCNetSDK.NET_SDK_INIT_CFG_SDK_PATH, strComPath.getPointer());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // SDK初始化，和进程保持同步，仅需要调用一次
        boolean initSuc = hCNetSDK.NET_DVR_Init();
        System.out.println("HCNetSDK 初始化：" + initSuc);
        if (initSuc) {
            // 设置连接时间
            hCNetSDK.NET_DVR_SetConnectTime(3 * 1000, 5);
            // 设置重连时间
            hCNetSDK.NET_DVR_SetReconnect(120 * 1000, true);
            // 开启SDK日志打印
            hCNetSDK.NET_DVR_SetLogToFile(3, System.getProperty("user.dir") + "\\log", false);
        }
    }

    // 获取设备
    public HikvisionClient getDevice(String sIP) {
        return clientMap.getOrDefault(sIP, null);
    }

    // 获取设备
    public HikvisionClient getDevice(String sIP, short sPort, String sUserName, String sPassword) {
        HikvisionClient client = getDevice(sIP);
        if (hCNetSDK != null && client == null) {
            // 登录设备
            client = new HikvisionClient(hCNetSDK, sIP, sPort, sUserName, sPassword);
            int userId = client.login();
            if (userId == -1) {
                client = null;
            } else {
                clientMap.put(sIP, client);
            }
        }
        return client;
    }

    // 设备检测
    public List<String> checkDevice() {
        List<String> deviceNos = new ArrayList<>();
        clientMap.forEach((key, client) -> {
            if (client.getState() != 0) {
                client.closeAlarmChan();    // 关闭布控
                client.logout();            // 退出登录
                client.login();             // 登陆设备
                client.setupAlarmChan();    // 设置布控
            }else {
                deviceNos.add(client.getDeviceNo());
            }
        });
        return deviceNos;
    }

    // 释放资源
    public void cleanup() {
        if (!hCNetSDK.NET_DVR_Cleanup()) {
            System.err.println("HCNetSDK 释放资源失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
        } else {
            System.out.println("HCNetSDK 释放资源！");
        }
    }
}
